a11y: Improve child notification for toplevels
authorMatthias Clasen <mclasen@redhat.com>
Sat, 24 Oct 2020 17:13:07 +0000 (13:13 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 24 Oct 2020 17:13:07 +0000 (13:13 -0400)
We need to translate the list model position into
an accessible tree position, since hidden toplevels
will be skipped.

While we are at it, add an api for this notification
that will be used in the next commit.

gtk/a11y/gtkatspiroot.c
gtk/a11y/gtkatspirootprivate.h

index 8c35fb6a29c93bff7c9198d0c682ac9f63e04837..21beb2eab3b38f8ed360c22e4fa1cd9276b9ec93 100644 (file)
@@ -412,8 +412,59 @@ root_toplevels__items_changed (GtkAtSpiRoot *self,
                                guint         added,
                                GListModel   *toplevels)
 {
-  GtkWidget *window = g_list_model_get_item (self->toplevels, position);
-  GVariant *window_ref = NULL;
+  if (added == 1 && removed == 0)
+    {
+      GtkWidget *window;
+
+      window = GTK_WIDGET (g_list_model_get_item (self->toplevels, position));
+      gtk_at_spi_root_child_changed (self,
+                                     GTK_ACCESSIBLE_CHILD_STATE_ADDED,
+                                     G_MAXUINT,
+                                     window);
+      g_object_unref (window);
+    }
+  else if (added == 0 && removed == 1)
+    {
+      gtk_at_spi_root_child_changed (self,
+                                     GTK_ACCESSIBLE_CHILD_STATE_REMOVED,
+                                     position,
+                                     NULL);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+}
+
+void
+gtk_at_spi_root_child_changed (GtkAtSpiRoot             *self,
+                               GtkAccessibleChildState   state,
+                               guint                     position,
+                               GtkWidget                *window)
+{
+  guint n, i;
+  int idx = 0;
+  GVariant *window_ref;
+
+  /* We can be called either with a valid position and window == NULL
+   * or with position == G_MAXUINT and a valid window. In both cases,
+   * we need to determine the index of where the removed object would
+   * have been in the accessible tree.
+   */
+  for (i = 0, n = g_list_model_get_n_items (self->toplevels); i < n; i++)
+    {
+      GtkAccessible *item = g_list_model_get_item (self->toplevels, i);
+
+      g_object_unref (item);
+
+      if (i == position || item == GTK_ACCESSIBLE (window))
+        break;
+
+      if (!gtk_accessible_should_present (item))
+        continue;
+
+      idx++;
+    }
 
   if (window == NULL)
     {
@@ -426,23 +477,12 @@ root_toplevels__items_changed (GtkAtSpiRoot *self,
       window_ref = gtk_at_spi_context_to_ref (GTK_AT_SPI_CONTEXT (context));
     }
 
-  if (added == 1 && removed == 0)
-    gtk_at_spi_emit_children_changed (self->connection,
-                                      self->root_path,
-                                      GTK_ACCESSIBLE_CHILD_STATE_ADDED,
-                                      position,
-                                      gtk_at_spi_root_to_ref (self),
-                                      window_ref);
-  else if (removed == 1 && added == 0)
-    gtk_at_spi_emit_children_changed (self->connection,
-                                      self->root_path,
-                                      GTK_ACCESSIBLE_CHILD_STATE_REMOVED,
-                                      position,
-                                      gtk_at_spi_root_to_ref (self),
-                                      window_ref);
-
-  if (window != NULL)
-    g_object_unref (window);
+  gtk_at_spi_emit_children_changed (self->connection,
+                                    self->root_path,
+                                    state,
+                                    idx,
+                                    gtk_at_spi_root_to_ref (self),
+                                    window_ref);
 }
 
 static void
index 0ce5e6b6935eda37036f850e100591adf47f3f77..12cba410855bd8c18da4ea4c5a1d4d00125109ed 100644 (file)
@@ -42,4 +42,10 @@ gtk_at_spi_root_get_cache (GtkAtSpiRoot *self);
 GVariant *
 gtk_at_spi_root_to_ref (GtkAtSpiRoot *self);
 
+void
+gtk_at_spi_root_child_changed (GtkAtSpiRoot             *self,
+                               GtkAccessibleChildState   state,
+                               guint                     position,
+                               GtkWidget                *window);
+
 G_END_DECLS